package com.lxr0860.lxr0860production_test.utils;

import android.util.Log;

import com.jhxd.serial.serialService;

public class PsamControl {
    private static int fd = -1;
    private static boolean ifopensuccess = false;
    private static int readsize;
    private static int ICType;
    //设置波特率
    private static final String DATA_BAUDSET = "AA 55 00 04 15 03 1C";

    /**
     * 串口发送指令 start
     */
    /*//设置波特率
    public static final String DATA_BAUDSET = "AA 55 00 04 15 03 1C";
    //IC初始化_小卡
    public static final String DATA_ICINIT_01 = "AA 66 00 04 37 00 3B";
    //IC初始化_大卡
    public static final String DATA_ICINIT_10 = "AA 66 00 04 37 10 4b";

    //取随机数_小卡
    public static final String DATA_GETRANDOMDATA_01 = "AA 66 00 09 38 00 00 84 00 00 08 CD";
    //取随机数_大卡
    public static final String DATA_GETRANDOMDATA_10 = "AA 66 00 09 38 01 00 84 00 00 08 CE";

    //加密_选择文件_小卡
    public static final String ENCRY_DATA_SELECTEFILE_01 = "aa 66 00 0b 38 00 00 a4 00 00 02 02 00 eb";
    //加密_选择文件_大卡
    public static final String ENCRY_DATA_SELECTEFILE_10 = "aa 66 00 0b 38 10 00 a4 00 00 02 02 00 fb";

    //加密_DES初始化_小卡
    public static final String ENCRY_DATA_DES_INIT_01 = "aa 66 00 11 38 00 80 1a 29 02 08 e0 04 00 00 fb 12 0b 09 1b";
    //加密_DES初始化_大卡
    public static final String ENCRY_DATA_DES_INIT_10 = "aa 66 00 11 38 10 80 1a 29 02 08 e0 04 00 00 fb 12 0b 09 2b";

    //加密_DES计算 小卡
    public static final String ENCRY_DATA_DES_01 = "aa 66 00 19 38 00 80 fa 00 00 10 88 88 88 88 99 99 99 99 88 88 88 88 99 99 99 99 e3";
    //加密_DES计算 大卡
    public static final String ENCRY_DATA_DES_10 = "aa 66 00 19 38 10 80 fa 00 00 10 88 88 88 88 99 99 99 99 88 88 88 88 99 99 99 99 f3";

    //加密 响应数据 小卡
    public static final String ENCRY_DATA_GETRESPONSEDATA_01 = "AA 66 00 09 38 00 00 C0 00 00 10 11";
    //加密 响应数据 大卡
    public static final String ENCRY_DATA_GETRESPONSEDATA_10 = "AA 66 00 09 38 10 00 C0 00 00 10 21";

    //解密 选择文件 小卡
    public static final String DECR_DATA_SELECTEFILE_01 = "aa 66 00 0b 38 00 00 a4 00 00 02 02 00 eb";
    //解密 选择文件 大卡
    public static final String DECR_DATA_SELECTEFILE_10 = "aa 66 00 0b 38 10 00 a4 00 00 02 02 00 fb";

    //解密 DES初始化 小卡
    public static final String DECR_DATA_DES_01 = "aa 66 00 12 38 00 80 1a 27 02 08 e0 04 00 00 4d aa 00 3e 09 37";
    //解密 DES初始化 大卡
    public static final String DECR_DATA_DES_10 = "aa 66 00 12 38 10 80 1a 27 02 08 e0 04 00 00 4d aa 00 3e 09 47";

    //数据解密 小卡
    public static final String DECR_data_DataDecr_01 = "aa 66 00 19 38 00 80 fa 00 00 10 21 a5 a4 93 86 b8 51 4d 70 19 93 3a 4a 92 82 1f 87";
    //数据解密 大卡
    public static final String DECR_data_DataDecr_10 = "aa 66 00 19 38 10 80 fa 00 00 10 21 a5 a4 93 86 b8 51 4d 70 19 93 3a 4a 92 82 1f 97";

    //解密 响应数据 小卡
    public static final String DECR_data_GetRandomData_01 = "AA 66 00 09 38 00 00 C0 00 00 10 11";
    //解密 响应数据 大卡
    public static final String DECR_data_GetRandomData_10 = "AA 66 00 09 38 10 00 C0 00 00 10 21";
   */


    /** 串口发送指令 end*/

    /**
     * IC上下电
     *
     * @param isOn 1：上电， 0： 下电
     * @return
     */
    public static int ICC_interface_power(int isOn) {
        if (isOn == 1) {
            //上电
            if (serialOpen()) {
                if (ICC_setBaud() == 1) {
                    return 0;
                }else{
                    return -1;
                }
            } else {
                return -1;
            }
        } else if (isOn == 0) {
            //下电
            if (serialClose()) {
                return 0;
            } else {
                return -1;
            }
        } else {
            return -2;
        }
    }

    /**
     * 选择卡座
     *
     * @param sock_num
     * @return
     */
    public static int ICC_select_sock(int sock_num) {
        if (sock_num == 1) {
            //小卡座
            ICType = 1;
            return 0;
        } else if (sock_num == 2) {
            //大卡座
            ICType = 2;
            return 0;
        } else {
            Log.d("TAG","Invalid parameter");
            return -2;

        }

    }

    /**
     * 检查是否有卡
     * @return
     */
    public static int ICC_sock_check(){
        String DATA_GETRANDOMDATA;

        if (ICType == 1) {
            DATA_GETRANDOMDATA = "AA 66 00 09 38 00 00 84 00 00 08 CD";
        } else if (ICType == 2) {
            DATA_GETRANDOMDATA = "AA 66 00 09 38 01 00 84 00 00 08 CE";

        } else {
            Log.d("TAG","No card selected");
            return 0;
        }
        //发送
        String dataToPort = SendDataToPort(DATA_GETRANDOMDATA);
        //aa 55 00 00 37 XX
        if (dataToPort.length() < 12) {
            return 0;
        }
        Log.d("msgStr", dataToPort);
        String statusStr = dataToPort.substring(8, 10);
        Log.d("status", statusStr);

        if (statusStr.equals("38")) {
            String dataStr = dataToPort.substring(10, dataToPort.length() - 6);
            Log.d("reData", dataStr);
            String statusCode = dataToPort.substring(dataToPort.length() - 6, dataToPort.length() - 2);
            Log.d("statusCode", statusCode);

                if (statusCode.equals("9000")||statusCode.equals("6110")) {
                    return 1;
                } else {
                    return 0;
                }
        } else {
            return 0;

        }
    }

    /**
     * IC复位
     *
     * @return
     */
    public static void ICC_cpucard_ATR(ICCTPDUDataListener serialPortDataListener) {
        String dataToPort;
        String DATA_ICINIT;

        if (ICType == 1) {
            //小卡复位
            DATA_ICINIT = "AA 66 00 04 37 00 3B";

        } else if (ICType == 2) {
            //大卡
            DATA_ICINIT = "AA 66 00 04 37 10 4b";

        } else {
            serialPortDataListener.ICCResponseDataCallback(-2, "", 0, "");
            return;
        }

        dataToPort = SendDataToPort(DATA_ICINIT);

        if (dataToPort.length() < 12) {
            serialPortDataListener.ICCResponseDataCallback(-1, "", 0, "");
            return;
        }
        Log.d("msgStr", dataToPort);
        String statusStr = dataToPort.substring(8, 10);
        Log.d("status", statusStr);
        if (statusStr.equals("37")) {
            String dataStr = dataToPort.substring(10, dataToPort.length() - 2);
            Log.d("reData", dataStr);
            serialPortDataListener.ICCResponseDataCallback(0, dataStr, dataStr.length()/2, "");
        } else {
            serialPortDataListener.ICCResponseDataCallback(-1, "", 0, "");
        }
    }

    /**
     * 取随机数
     *
     * @return
     */
    public static void ICC_T0_TPDU_RandomData(ICCTPDUDataListener serialPortDataListener) {
        String DATA_GETRANDOMDATA;
        if (ICType == 1) {
            DATA_GETRANDOMDATA = "AA 66 00 09 38 00 00 84 00 00 08 CD";
        } else if (ICType == 2) {
            DATA_GETRANDOMDATA = "AA 66 00 09 38 01 00 84 00 00 08 CE";
        } else {
            serialPortDataListener.ICCResponseDataCallback(-2,"",0,"");
            return;
        }
        int dataPro = dataPro(1, DATA_GETRANDOMDATA, serialPortDataListener);
        if ( dataPro!=0) {
            serialPortDataListener.ICCResponseDataCallback(dataPro,"",0,"");
        }
    }

    /**
     * 加密ICC_TO_TPDU
     * @param dir  地址
     * @param keyID p2
     * @param gene  des初始化的data
     * @param dataIn des计算的data
     * @param serialPortDataListener  ICC数据返回监听类
     * @return
     */
    public static void ICC_TO_TPDU_Encry(byte[] dir, byte keyID, byte[] gene,long genLen,byte[] dataIn, long dataLen,ICCTPDUDataListener serialPortDataListener) {
        if ((genLen != 8) || (dataLen % 16 != 0)
                || (dataLen > 0xA0)) {
            Log.d("TAG","input DaLen error");
            serialPortDataListener.ICCResponseDataCallback(-1, "", 0, "");
            return ;
        }
        int ret;
        //选择文件
        //"aa 66 00 0b 38 00 00 a4 00 00 02 02 00 eb";
        ret = ICC_TO_TPDU(0, "00", "a4", "00", "00", "02", dir, serialPortDataListener);

        if (ret != 0) {
            Log.d("TAG","Encry select file fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
            return;
        }

        //DES初始化
        //aa 66 00 11 38 00 80 1a 29 02 08 e0 04 00 00 fb 12 0b 09 1b
        ret = ICC_TO_TPDU(0, "80", "1a", "29", MyUtils.hex2DebugHexString(keyID), "08", gene, serialPortDataListener);
        if (ret != 0) {
            Log.d("TAG","Encry des init fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
            return;
        }


        //des计算
        //aa 66 00 19 38 00 80 fa 00 00 10 88 88 88 88 99 99 99 99 88 88 88 88 99 99 99 99 e3
        ret = ICC_TO_TPDU(0, "80", "fa", "00", "00", "10", dataIn, serialPortDataListener);
        if (ret != 0) {
            Log.d("TAG","Encry des calculation fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
            return;
        }

        //读响应数据
        //AA6600093800 00 C0 00 00 10
        ret = ICC_TO_TPDU(1, "00", "c0", "00", "00", "10", serialPortDataListener);
        if (ret != 0) {
            Log.d("TAG","Encry get response data fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
        }

    }

    /**
     * 解密ICC_TO_TPDU
     *
     * @param serialPortDataListener
     * @return
     */
    public static void ICC_TO_TPDU_Decr(byte[] dir, byte keyID, byte[] gene,long genLen,byte[] dataIn,  long dataLen,ICCTPDUDataListener serialPortDataListener) {
        if ((genLen != 8) || (dataLen % 16 != 0)
                || (dataLen > 0xA0)) {
            Log.d("TAG","Decr input DaLen error");
            serialPortDataListener.ICCResponseDataCallback(-1, "", 0, "");

            return ;
        }
        int ret;
        //解密选择文件
        //"aa 66 00 0b 38 00 00 a4 00 00 02 02 00 eb";
        ret = ICC_TO_TPDU(0, "00", "a4", "00", "00", "02", dir, serialPortDataListener);
        if (ret != 0) {
            Log.d("TAG","Decr select file fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
            return;
        }


        //des初始化
        //aa 66 00 11 38 00 80 1a 27 02 08 e0 04 00 00 4d aa 00 3e 09 36
        ret = ICC_TO_TPDU(0, "80", "1a", "27", MyUtils.hex2DebugHexString(keyID), "08", gene, serialPortDataListener);
        if (ret != 0) {
            Log.d("TAG","Decr des init fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
            return;
        }


        //des计算
        //aa 66 00 19 38 00 80 fa 00 00 10  21 a5 a4 93 86 b8 51 4d 70 19 93 3a 4a 92 82 1f  87
        ret = ICC_TO_TPDU(0, "80", "fa", "00", "00", "10", dataIn, serialPortDataListener);
        if (ret != 0) {
            Log.d("TAG","Decr des calculation fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
            return;
        }

        //解密读响应数据
        //AA 66 00 09 38 10 00 C0 00 00 10 XX
        ret = ICC_TO_TPDU(1, "00", "c0", "00", "00", "10", serialPortDataListener);
        if (ret!=0) {
            Log.d("TAG","Decr get response data fail");
            serialPortDataListener.ICCResponseDataCallback(ret, "", 0, "");
        }
    }

    /**
     * 设置波特率
     * @return
     */
    private static int ICC_setBaud(){
        if (ICC_set_baud()) {
            return 1;
        } else {
            return -1;
        }
    }

    /**
     * ICC 发送数据打包
     *
     * @param CLA
     * @param INS
     * @param P1
     * @param P2
     * @param P3
     * @param databuff
     * @param serialPortDataListener
     * @return
     */
    public static int ICC_TO_TPDU(int isIn, String CLA, String INS, String P1, String P2, String P3,
                                  byte[] databuff, ICCTPDUDataListener serialPortDataListener) {

//"aa 66 00 0b 38 00 00 a4 00 00 02 02 00 eb";
        String data = MyUtils.hex2DebugHexString(databuff).replace(" ", "");
        String dataBuffer = data.replace("aa", "aa00");
        dataBuffer = dataBuffer.replace("AA", "AA00");
        String witeData;
        //判断选择卡座
        if (ICType == 2) {
            witeData = "aa663810" + CLA + INS + P1 + P2 + P3 + dataBuffer;
        } else {
            witeData = "aa663800" + CLA + INS + P1 + P2 + P3 + dataBuffer;
        }
        System.out.print("beforIn:" + witeData + "\n");

        //计算数据长度
        String hexString = Integer.toHexString(witeData.length() / 2);
        while (hexString.length() < 4) {
            hexString = "0" + hexString;
        }
        StringBuilder stringBuilder = new StringBuilder(witeData);
        stringBuilder.insert(4, hexString);
        System.out.print("InsertData:" + hexString + "\n");

        //末尾添加Add8校验
        witeData = stringBuilder.toString();
        String addData = MyUtils.Add(witeData.substring(4));
        witeData = witeData + addData;
        System.out.print("ADD8:" + addData + "\n");
        System.out.print("witeData:" + witeData + "\n");
        return dataPro(isIn, witeData, serialPortDataListener);
    }
    /**
     * ICC 发送数据打包
     *
     * @param CLA
     * @param INS
     * @param P1
     * @param P2
     * @param P3
     * @param serialPortDataListener
     * @return
     */
    public static int ICC_TO_TPDU(int isIn, String CLA, String INS, String P1, String P2, String P3, ICCTPDUDataListener serialPortDataListener) {

//"aa 66 00 0b 38 00 00 a4 00 00 02 02 00 eb";
        String witeData;
        if (ICType == 2) {
            witeData = "aa663810" + CLA + INS + P1 + P2 + P3;
        } else {
            witeData = "aa663800" + CLA + INS + P1 + P2 + P3;
        }
        //计算数据长度
        String hexString = Integer.toHexString(witeData.length() / 2);
        while (hexString.length() < 4) {
            hexString = "0" + hexString;
        }
        StringBuilder stringBuilder = new StringBuilder(witeData);
        stringBuilder.insert(4, hexString);
        System.out.print("InsertData:" + hexString + "\n");
        witeData = stringBuilder.toString();
        //添加Add8校验
        witeData = witeData + MyUtils.Add(witeData.substring(4));
        System.out.print("ADD8:" + MyUtils.Add(witeData.substring(4)) + "\n");
        System.out.print("witeData:" + witeData + "\n");
        //发送、接收处理
        return dataPro(isIn, witeData, serialPortDataListener);

    }

    /**
     * 数据发送和接收处理
     *
     * @param isIn
     * @param serialPortDataListener
     * @param sendData
     * @return
     */
    private static int dataPro(int isIn, String sendData, ICCTPDUDataListener serialPortDataListener) {
        //发送
        String dataToPort = SendDataToPort(sendData);
        //aa 55 00 00 37 XX
        if (dataToPort.length() < 12) {
            if (isIn == 0) {
                return -1;
            } else {
//                serialPortDataListener.ICCResponseDataCallback(-1, "", 0, "");
                return -1;
            }
        }
        Log.d("msgStr", dataToPort);
        String statusStr = dataToPort.substring(8, 10);
        Log.d("status", statusStr);

        if (statusStr.equals("38")) {
            String dataStr = dataToPort.substring(10, dataToPort.length() - 6);
            Log.d("reData", dataStr);
            String statusCode = dataToPort.substring(dataToPort.length() - 6, dataToPort.length() - 2);
            Log.d("statusCode", statusCode);
            if (isIn == 0) {
                if (statusCode.equals("9000")||statusCode.equals("6110")) {
                    return 0;
                } else {
                    try {
                        return Integer.parseInt(statusCode);
                    }catch (Exception e){
                        return -1001;
                    }
                }
            } else {
                if (statusCode.equals("9000")||statusCode.equals("6110")) {
                    serialPortDataListener.ICCResponseDataCallback(0, dataStr, dataStr.length()/2, statusCode);
                    return 0;
                } else {
                    serialPortDataListener.ICCResponseDataCallback(-2, dataStr, dataStr.length()/2, statusCode);
                    return -1;
                }
            }

        } else {
            if (isIn == 0) {
                return -1;
            } else {
//                serialPortDataListener.ICCResponseDataCallback(-1, "", 0, "");
                return -1;
            }
        }
    }

    /**
     * 串口数据发送处理
     *
     * @param data
     */
    private static String SendDataToPort(String data) {

        String sendString = data + "\r\n";
        if (sendString.length() <= 0)
            return "";

        System.out.println("------writeSize: " + sendString.length() + "------");
        System.out.println("------writeData: " + sendString + "------");

        byte[] tempBytes = MyUtils.hexStringToBytes(sendString);
        serialService.serialWrite(fd, tempBytes, tempBytes.length);

        byte[] readdata = new byte[1024];
        int readlen = 1024;
        int count = 0;
        while (true) {
            try {
                readsize = serialService.serialRead(fd, readdata, readlen);
                if (readsize > 0) {
                    System.out.println("------readSize:" + readsize + "------");
                    byte[] mytempBytes = new byte[readsize];
                    for (int i = 0; i < mytempBytes.length; i++) {
                        mytempBytes[i] = readdata[i];
                    }
                    String recvdataString = MyUtils.hex2DebugHexString(mytempBytes).replace(" ", "");
                    System.out.println("------recvData:" + recvdataString + "------");
                    return recvdataString;
                }

                Thread.sleep(200);
                if (count >= 5) {
                    return "";
                }
                count++;
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * 设置波特率 19200
     *
     * @return
     */
    private static boolean ICC_set_baud() {
        String sendString = PsamControl.DATA_BAUDSET + "\r\n";
        if (sendString.length() <= 0)
            return false;

        System.out.println("------writeSize: " + sendString.length() + "------");
        System.out.println("------writeData: " + sendString + "------");

        byte[] tempBytes = MyUtils.hexStringToBytes(sendString);
        serialService.serialWrite(fd, tempBytes, tempBytes.length);

        byte[] readdata = new byte[1024];
        int readlen = 1024;
        int count = 0;
        while (true) {
            try {
                readsize = serialService.serialRead(fd, readdata, readlen);
                if (readsize > 0) {
                    System.out.println("------readSize:" + String.valueOf(readsize) + "------");
                    byte[] mytempBytes = new byte[readsize];
                    for (int i = 0; i < mytempBytes.length; i++) {
                        mytempBytes[i] = readdata[i];
                    }
                    String recvdataString = MyUtils.hex2DebugHexString(mytempBytes).replace(" ", "");
                    System.out.println("------recvData:" + recvdataString + "------");

                    String statusStr = recvdataString.substring(8, 10);
                    Log.d("status", statusStr);
                    String dataStr = recvdataString.substring(10, recvdataString.length() - 2);
                    Log.d("reData", dataStr);
                    if (statusStr.equals("15")) {
                        return true;
                    } else {
                        return false;
                    }
                }

                Thread.sleep(200);
                if (count >= 5) {
                    return false;
                }
                count++;
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
        }
    }

    /**
     * 打开串口
     *
     * @return
     */
    private static boolean serialOpen() {
        String path = "/dev/ttyS4";
        int baud = 19200;
        int databits = 8;
        int parity = 0;
        int stopbits = 1;
        if (ifopensuccess) {
            System.out.println("----serialPort is already open-----");
            return true;
        }

        if ((fd = serialService.serialOpen(path)) < 0) {
            System.out.println("----open serialPort error-----");
            ifopensuccess = false;
            return false;
        } else {
            System.out.println("------fd：" + fd + "------" + baud);
            if (serialService.serialPortSetting(fd, baud, databits, parity, stopbits) < 0) {
                System.out.println("----open serialPort error-----");
                ifopensuccess = false;
                return false;
            } else {
                System.out.println("----open serialPort success-----");
                ifopensuccess = true;
               return true;
            }
        }
    }

    /**
     * 关闭串口
     */
    private static boolean serialClose() {
        ifopensuccess = false;
        if (serialService.serialClose(fd) < 0) {
            System.out.println("------close serialPort error------");
            return false;
        } else {
            System.out.println("------close serialPort success------");
            return true;
        }
    }

 /*   public static void setSerailDataListener(SerialPortDataListener listener) {
//        new recDataThread().start();
        dataListener = listener;

    }

    public static void unSerailDataListener() {
        dataListener = null;
    }*/
    public interface ICCTPDUDataListener {
        void ICCResponseDataCallback(int status, String Data, int DataLen, String statusCode);
    }

    /**
     * 串口数据读取
     */
    /*static class recDataThread extends Thread {
        byte[] readdata = new byte[1024];
        int readlen = 1024;

        public void run() {
            while (ifopensuccess) {
                if (ifopensuccess == false) {
                    System.out.println("------Close Rece Thread------");
                    break;
                }

                try {
                    readsize = serialService.serialRead(fd, readdata, readlen);
                    if (readsize > 0) {
                        System.out.println("------readSize:" + String.valueOf(readsize) + "------");
                        byte[] tempBytes = new byte[readsize];
                        for (int i = 0; i < tempBytes.length; i++) {
                            tempBytes[i] = readdata[i];
                        }
                        String recvdataString = hex2DebugHexString(tempBytes);
                        System.out.println("------recvData:" + recvdataString + "------");

                        if (dataListener != null) {
                            dataListener.SerialDataCallback(recvdataString);
                        }
                    }
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }*/
}

